from rest_framework import serializers
from django_redis import get_redis_connection
from rest_framework_jwt.settings import api_settings
from .models import User
from celery_tasks.send_email.tasks import send_verify_email
import re


class UserRegisterSerializer(serializers.ModelSerializer):
    """用户注册序列化器"""
    password2 = serializers.CharField(label="确认密码", write_only=True)
    sms_code = serializers.CharField(label="手机验证码", write_only=True)
    allow = serializers.BooleanField(label="是否同意协议", write_only=True)
    token = serializers.CharField(label="JWT身份验证token", read_only=True)

    class Meta:
        model = User
        fields = ("id", "username", "password", "password2", "mobile", "sms_code", "allow", "token")
        extra_kwargs = {
            "username": {
                "min_length": 5,
                "max_length": 20,
                "error_messages": {
                    "min_length": "用户名字符个数不可少于5个",
                    "max_length": "用户名字符个数不能超过20个"
                }
            },
            "password": {
                "write_only": True,
                "min_length": 8,
                "max_length": 20,
                "error_messages": {
                    "min_length": "密码不能少于5位",
                    "max_length": "密码不能超过20位"
                }
            }
        }

    # 校验手机号格式
    def validate_mobile(self, value):
        if not re.match(r"^1[3-9][0-9]{9}$", value):
            return serializers.ValidationError("手机号格式不正确")
        return value

    # 校验是否同意注册协议
    def validate_allow(self, value):
        if not value:
            return serializers.ValidationError("未同意注册协议")
        return value

    # 校验手机验证码,密码是否相同
    def validate(self, attrs):
        mobile = attrs["mobile"]
        sms_code = attrs["sms_code"]
        password = attrs["password"]
        password2 = attrs["password2"]

        # 手机验证码
        redis_conn = get_redis_connection("verify_codes")
        real_sms_code = redis_conn.get("sms_code_%s" % mobile)
        if not real_sms_code:
            raise serializers.ValidationError("手机验证码不存在")
        redis_conn.delete("sms_code_%s" % mobile)
        if sms_code != real_sms_code.decode():
            raise serializers.ValidationError("手机验证码错误")

        # 两次密码是否相同
        if password != password2:
            raise serializers.ValidationError("两次输入的密码不相同")

        return attrs

    # 创建用户数据
    def create(self, validated_data):
        del validated_data["password2"]
        del validated_data["sms_code"]
        del validated_data["allow"]

        user = super().create(validated_data)
        user.set_password(validated_data["password"])
        user.save()

        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token
        user.save()

        return user


class UserInfoSerializer(serializers.ModelSerializer):
    """用户详情页序列化器"""
    class Meta:
        model = User
        fields = ("id", "username", "mobile", "email", "email_active")


class EmailBindingSerializer(serializers.ModelSerializer):
    """用户邮箱绑定序列化器"""
    class Meta:
        model = User
        fields = ("id", "email")

    def update(self, instance, validated_data):
        email = validated_data["email"]
        instance.email = email
        instance.save()

        verify_url = instance.generate_email_verify_url()
        send_verify_email.delay(email, verify_url)

        return instance


